/**
 * 
 */
package ar.uba.dc.tlen.src.main;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;

import ar.uba.dc.tlen.src.grammar.Gramatica;
import ar.uba.dc.tlen.src.production.Produccion;
import ar.uba.dc.tlen.src.symbols.Caracter;
import ar.uba.dc.tlen.src.symbols.NoTerminal;

/**
 * Esta clase se encarga de armar la tabla.
 * 
 */
public class PrecedenciaSimple implements AnalizadorSintactico {
	
	
	/*El algoritmo dado en clase es:
	 * Para c/par de simbolos continuos x e y
	 * 		Agregar(X=. Y)
	 * 		Agregar(x <. P+ (y))
	 * 		Agregar(U+(x) .> P*(v))
	 * Agregar($ <. P+(simbolo inicial))
	 * Agregar(U+(x) .> P*(v))*/
	public Tabla analizar(Gramatica gramatica) {
		TreeSet<Caracter> v = new TreeSet<Caracter>();
		v.addAll(gramatica.getNoTerminales());
		v.addAll(gramatica.getTerminales());
		return null;//TODO Terminal el algoritmo
		
	}
	/*Este metodo 'tiene' el mismo comportamiento que el U+ dado en la clase
	 * de precedencia simple:
	 * U+(x) = {y <belong> V / x =>+ Y<alpha>}
	 * */
	TreeSet<Caracter> uMas(Gramatica gramatica,Caracter caracter){
		TreeSet<Caracter> primeros= new TreeSet<Caracter>();
		Caracter actual;
		Iterator<Caracter> it=caracter.getDerecha().iterator();
		while(it.hasNext()){
			actual= it.next();
			//TODO Chequear el comportamiento del iterador.
			if(actual.getClass() == NoTerminal.class){
				primeros.addAll(primerosDeProducciones(gramatica, (NoTerminal)actual));
			}
		} 
		return primeros;
	}
	/*Dado un no terminal de la gramatica busco con que no terminal inician 
	 * todas sus producciones. Si empiezan con un noTerminal ademas busco 
	 * recursivamente.
	 * */
	private TreeSet<Caracter> primerosDeProducciones(Gramatica gramatica, NoTerminal noterminal) {
		Caracter actual;
		TreeSet<Caracter> primeros= new TreeSet<Caracter>();
		Iterator<Produccion> it= noterminal.getPartesDerecha().iterator();
		while(it.hasNext()){
			actual=it.next().getDerecha().get(0);
			primeros.add(actual);
			if(actual.getClass() == NoTerminal.class){
				primeros.addAll(primerosDeProducciones(gramatica, noterminal));
			}
		}
		return primeros;
	}
	
	/*Este metodo 'tiene' el mismo comportamiento que el P* dado en la clase
	 * de precedencia simple:
	 * P*(x) = {Vt <intersection> (X <union> P+(x))}
	 * */
	TreeSet<Caracter> pPor(Gramatica gramatica, Caracter caracter){
		TreeSet<Caracter> xUnionPMas= new TreeSet<Caracter>();
		xUnionPMas.add(caracter);
		xUnionPMas.addAll(pMas(gramatica,caracter));
		//TODO testear el comportamiento de retainAll
		gramatica.getTerminales().retainAll(xUnionPMas);
		return gramatica.getTerminales();
	}
	/*Este metodo 'tiene' el mismo comportamiento que el P+ dado en la clase
	 * de precedencia simple:
	 * P+(x) = {y <belong> V/ x=>+ <alpha>Y}
	 * */	
	TreeSet<Caracter> pMas(Gramatica gramatica, Caracter caracter){
		TreeSet<Caracter> ultimos= new TreeSet<Caracter>();
		Caracter actual;
		Iterator<Caracter> it=caracter.getDerecha().iterator();
		while(it.hasNext()){
			actual= it.next();
			//TODO Chequear el comportamiento del iterador.
			if(actual.getClass() == NoTerminal.class){
				ultimos.addAll(ultimosDeProducciones(gramatica, (NoTerminal)actual));
			}
		}
		return ultimos;
	}
	
	private TreeSet<Caracter> ultimosDeProducciones(Gramatica gramatica, NoTerminal noterminal) {
		Caracter actual;
		TreeSet<Caracter> ultimos= new TreeSet<Caracter>();
		Iterator<Produccion> it= noterminal.getPartesDerecha().iterator();
		while(it.hasNext()){
			ArrayList<Caracter> caracteres = it.next().getDerecha(); 
			actual= caracteres.get(caracteres.size()-1);
			ultimos.add(actual);
			if(actual.getClass() == NoTerminal.class){
				ultimos.addAll(ultimosDeProducciones(gramatica, noterminal));
			}
		}
		return ultimos;
	}
	
	TreeSet<Caracter> igual(Gramatica gramatica, Caracter caracter){
		return caracter.getDerecha();
	}

}
